/*
 * Created on Feb 21, 2006
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package fr.jade.service.fm.reactor;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.factory.GenericFactory;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.api.type.ComponentType;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.api.type.TypeFactory;

import fr.jade.base.JadeBaseComponent;
import fr.jade.reflex.api.control.ReflexController;
import fr.jade.reflex.util.Reflex;
import fr.jade.service.fm.deployment.DeploymentTask;
import fr.jade.service.fm.deployment.FakeComponentTask;
import fr.jade.service.fm.deployment.FractalComponentTask;
import fr.jade.service.fm.deployment.NewComponentTask;
import fr.jade.util.FractalNavigator;
import fr.jade.util.FractalUtil;
import fr.jade.util.JadeException;

public class ComponentPolicy extends JadeBaseComponent implements Policy{

  public int getPriorityLevel(){
    return 0;
  }
  
	public Set<DeploymentTask> execute(Map<Component, NewComponentTask> context, Set<Component> failedCmps_M, Set<Component> impactedCmps_M, Component newNode_M) throws JadeException{
	  log("Component Policy");
	  try{
	    GenericFactory gf_M = FractalUtil.getGenericFactory(newNode_M);
	    Set<DeploymentTask> tasks= new HashSet<DeploymentTask>();
  	  for (Component cmp_M : failedCmps_M) {
          String name = FractalUtil.getNameController(cmp_M).getFcName();
          ReflexController rc_M = Reflex.getReflexController(cmp_M);
          String controllerDesc_E = rc_M.getReflexAttribute("controllerDesc");
          String contentDesc_E = rc_M.getReflexAttribute("contentDesc");
          ComponentType type_E = extractCmpType((ComponentType) (cmp_M.getFcType()), gf_M);
          log(name + " " + controllerDesc_E + " " + contentDesc_E + " " + FractalNavigator.getName(newNode_M));
          DeploymentTask dt = new FractalComponentTask(gf_M, type_E, controllerDesc_E, contentDesc_E, name);
          context.put(cmp_M, (NewComponentTask)dt);
          tasks.add(dt);
       }
  	  for (Component cmp_M : impactedCmps_M) {
  	    log(FractalNavigator.getName(cmp_M) + "(fake)");
        DeploymentTask dt = new FakeComponentTask(cmp_M);
        context.put(cmp_M, (NewComponentTask)dt);
        tasks.add(dt);
     }
  	  return tasks;
	  }catch(NoSuchInterfaceException e){
	    throw new JadeException("cannot create FractalComponentTask", e);
	  } catch (InstantiationException e) {
	    throw new JadeException("cannot create FractalComponentTask", e);
    }
  }
	
	/*
	 * extract from the meta cmp type the type used to create the component 
	 */
	protected ComponentType extractCmpType(ComponentType t, GenericFactory gf_E) throws NoSuchInterfaceException, InstantiationException{

		String itfName = null;
		InterfaceType[] itRes = null;

		TypeFactory tf = FractalUtil.getTypeFactory(((Interface)gf_E).getFcItfOwner());

		InterfaceType[] it = t.getFcInterfaceTypes();

		int j = 0;
		for (int i = 0; i < it.length; i++) {
			itfName = it[i].getFcItfName();

			if (!((itfName.equals("component")) || (itfName.endsWith("-controller")))) {
				j++;
			}
		}

		itRes = new InterfaceType[j];
		j = 0;
		for (int i = 0; i < it.length; i++) {
			itfName = it[i].getFcItfName();

			if (!((itfName.equals("component")) || (itfName.endsWith("-controller")))) {
				itRes[j] = it[i];
				j++;
			}
		}

		return tf.createFcType(itRes);

	}
	
}
